/* Copyright (c) 2004-2024 Peigen.info. All rights reserved. */

package info.peigen.hotpot.component.gateway.dianlan.facade.enums;

import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import info.peigen.hotpot.common.core.enums.Messageable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.beetl.sql.annotation.entity.EnumValue;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <b>(DianlanFrameSign)</b>
 * 这块枚举规则：
 * 1.点蓝调用我们的前缀加Dianlan
 * 2.如果是客户端一直推送的，后缀使用Push
 *
 * @author Peigen
 * @version 1.0.0
 * @since 2022/8/22
 */
@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum DianlanFrameSign implements Messageable {
    /** 为了对抗 Alibaba Java Coding 而存在的注释 */
    // passive
    Login("01", "登录认证"),
    LoginResponse("02", "登录认证应答"),
    HeartBeat("03", "充电桩心跳包"),
    HeartBeatResponse("04", "充电桩心跳包应答"),
    SettingTime("56", "对时设置"),
    SettingTimeResponse("55", "对时设置应答"),
    StubStatus("12", "读取实时监测数据"),
    StubStatusPush("13", "读取实时监测数据"),
    StartCharge("34", "启动充电"),
    StartChargeResponse("33", "启动充电应答"),
    StopCharge("36", "停止充电"),
    StopChargeResponse("35", "停止充电应答"),
    Recharge("42", "余额更新"),
    RechargeResponse("41", "余额更新应答"),
    SettingCard("44", "下发卡号"),
    SettingCardResponse("43", "下发卡号应答"),
    TransInformation("3B", "交易上送"),
    TransInformationResponse("40", "交易应答"),
    StubStopCharge("19", "电桩停止充电"),
    BillingModelSetting("58", "计费模型设置"),
    BillingModelSettingResponse("57", "计费模型设置应答"),
    BillingModelCheck("05", "计费模型验证"),
    BillingModelCheckResponse("06", "计费模型应答"),
    StubAwait("E7", "电桩待机"),
    StubAwaitResponse("E6", "电桩待机应答"),
    StubArm("E9", "机械臂指令"),
    StubArmResponse("E8", "机械臂指令应答"),
    StubSpearHead("EB", "充电枪指令"),
    StubSpearHeadResponse("EA", "充电枪指令应答"),
    BmsAndLiquidCoolingUnit("EF", "BMS及液冷机组通讯协议"),
    FireUnitStatusAlarm("EC", "灭火装置信息"),
    /** 不晓得啷格回事 */
    UNKNOWN("--", "不晓得啷格回事");

    /** 枚举值 */
    @EnumValue
    String code;

    /** 枚举描述 */
    String message;


    /**
     * 通过枚举<code>code</code>获得枚举
     *
     * @param code 枚举值
     *
     * @return DianlanFrameSign
     */
    public static DianlanFrameSign getByCode(String code) {
        return Stream.of(values())
                .filter(innerEnum -> StrUtil.equals(code, innerEnum.code()))
                .findFirst().orElse(UNKNOWN);
    }

    /**
     * 通过枚举<code>name</code>获得枚举
     *
     * @param name 枚举名
     *
     * @return DianlanFrameSign
     */
    public static DianlanFrameSign getByName(String name) {
        return Stream.of(values())
                .filter(innerEnum -> StrUtil.equalsIgnoreCase(name, innerEnum.name()))
                .findFirst().orElse(UNKNOWN);
    }

    /**
     * 获取全部枚举
     *
     * @return List<DianlanFrameSign>
     */
    public static List<DianlanFrameSign> getAllEnum() {
        return Lists.newArrayList(values());
    }

    /**
     * 获取全部枚举值
     *
     * @return List<String>
     */
    public static List<String> getAllEnumCode() {
        return getAllEnum().stream().map(DianlanFrameSign::code).collect(Collectors.toList());
    }

    /**
     * 通过code获取msg
     *
     * @param code 枚举值
     *
     * @return String
     */
    public static String getMsgByCode(String code) {
        return getByCode(code).message();
    }

    /**
     * 获取枚举code
     *
     * @param innerEnum 枚举
     *
     * @return code
     */
    public static String getCode(DianlanFrameSign innerEnum) {
        return Optional.ofNullable(innerEnum).map(DianlanFrameSign::code).orElse(UNKNOWN.code());
    }

    /**
     * map
     *
     * @return Map
     */
    public static Map<String, String> maps() {
        return Stream.of(values()).collect(Collectors.toMap(DianlanFrameSign::code, DianlanFrameSign::message));
    }

    /**
     * 该方法是为了避免NPE，安全获取枚举中的字段值
     */
    public static <T> T safeGet(DianlanFrameSign enumValue, Function<DianlanFrameSign, T> mapper, T defaultValue) {
        return Objects.isNull(enumValue) ? defaultValue : mapper.apply(enumValue);
    }

    /**
     * 该方法是为了避免NPE，安全获取枚举中的字段值，默认返回值是null
     */
    public static <T> T safeGet(DianlanFrameSign enumValue, Function<DianlanFrameSign, T> mapper) {
        return safeGet(enumValue, mapper, null);
    }

    /**
     * 该方法是为了避免NPE，安全获取枚举中的code值，默认返回值是null
     */
    public static String safeGetCode(DianlanFrameSign enumValue) {
        return safeGet(enumValue, Messageable::code, null);
    }

    /**
     * 判断给定的枚举，是否在列表中
     *
     * @param values 列表
     *
     * @return Boolean
     */
    public boolean isInList(DianlanFrameSign... values) {
        for (DianlanFrameSign e : values) {
            if (this == e) {
                return true;
            }
        }
        return false;
    }

    /**
     * @return Returns the code.
     */
    @Override
    public String code() {
        return code;
    }

    /**
     * @return Returns the message.
     */
    @Override
    public String message() {
        return message;
    }
}